#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "doss.h"

typedef struct
{
	int numX;  // frame number in x axis
	int numY;  // frame number in y axis
	int width;	// frame width 
	int height; // frame height
	int mnw;  // main frame width
	int mnh; // main frame height
} FRAMEVALUES_T;

static PROFILE_T s_profile;
static Style_t s_style;
static FRAMEVALUES_T val;

static void InfractRect(RECT& rect, int infract);
static void SetRect(RECT& rect, int l, int t, int w, int h);
static int InRect(RECT* rect, int x, int y);

/* ******************** Module APIS *********************/

int initLayout(PROFILE_T& profile, Style_t& style, FUNC_CB* fn)
{
	memcpy(&s_profile, &profile, sizeof(PROFILE_T));
	memcpy(&s_style, &style, sizeof(Style_t));

	s_profile.notify_cb = fn;
		
	return 0;
}

int setLayout(int x, int y, RATIO_WH_E rwh)
{
	s_profile.type = rwh;
	updateClientArea(x, y);
	return 0;
}

int updateClientArea(int x, int y)
{
	s_profile.clientX = x;
	s_profile.clientY = y;

	FUNC_CB* notify = s_profile.notify_cb;
	
	(*notify)(CMD_UPDATE, NULL); // notify the client

	int ww, hh, kk= 0;
	int xx = s_profile.x;
	int yy = s_profile.y;
	int width=0, height = 0;
	int yNum = 0;
	if (s_profile.layout_type == LO_NN)
	{
		if (s_profile.type == E_IMMOVABLE)
		{
			ww = s_profile.clientX/s_profile.xNum;
			yNum = s_profile.clientY/(ww*yy/xx);
			//		hh = s_profile.clientY/s_profile.xNum;
			width = ww;
			height = width*yy/xx;
		}
		else // E_MOVABLE
		{
			ww = s_profile.clientX/s_profile.xNum;
			hh = s_profile.clientY/s_profile.xNum;
			//		hh = s_profile.clientY/s_profile.xNum;
			width = ww;
			height = hh;
		}
	}
	else if(s_profile.layout_type = LO_NM)
	{

	}
	else 
	{
	}

	int aa = 0;
	int num = s_profile.xNum*yNum;
	FRAMEDISPLAY_T fs;
	while(aa <num)
	{
		fs.idFrame = aa +1;
		SetRect(fs.rect, (aa%s_profile.xNum)*width, (aa/s_profile.xNum)*height, width, height);
		InfractRect(fs.rect, -s_style.padding_l);
		(*notify)(CMD_UPDATE_FRAME, (void*) &fs);
		aa++;
	}

	int bb = 100;
	if (bb >90 )
	{
		LAYOUT_E type = LO_NM;
		(*notify)(CMD_NOTIFY_ADVISE_LAYOUT, &type);
	}

	val.numX = s_profile.xNum;
	val.numY = yNum;
	val.width = width;
	val.height = height;
	
	return 0;
}

// if -1 not in client; 0 in client but no item hit;  >0 item number
int hitTest(int x, int y)
{
	if (x <0 || y<0 || s_profile.clientX < x || s_profile.clientY < y)
		return -1;
	int aa = 0;
	int num = val.numX*val.numY;
	FRAMEDISPLAY_T fs;
	while(aa <num)
	{
		fs.idFrame = aa +1;
		SetRect(fs.rect, (aa%val.numX)*val.width, (aa/val.numY)*val.height, val.width, val.height);
		InfractRect(fs.rect, -s_style.padding_l);
		if (InRect(&fs.rect, x, y))
		{
			return aa+1;
		}
		aa++;
	}

	return 0;
}


/**************************** Help functions *******************************/
void InfractRect(RECT& rect, int infract)
{
	if (infract < 0)
	{
		if ((rect.r - rect.l) <infract || (rect.b-rect.t)<infract)
		{
			return ; // 
		}
	}
	rect.l -= infract;
	rect.t -= infract;
	rect.r += infract;
	rect.b += infract;
}

int InRect(RECT* rect, int x, int y)
{
	if (rect->l < x && rect->t < y && rect->r >x && rect->b >y)
		return 1;
	return 0;
}
void SetRect(RECT& rect, int l, int t, int w, int h)
{
	rect.l = l;
	rect.t = t;
	rect.r = l+w;
	rect.b = t+h;
}

void RegRect(RECT& rect)
{
	int tmp = 0;
	if (rect.l > rect.r)
	{
		tmp = rect.r;
		rect.r = rect.l;
		rect.l = tmp;
	}
	if (rect.t > rect.b)
	{
		tmp = rect.b;
		rect.b = rect.t;
		rect.t = tmp;
	}
}


